#pragma once

#include "types.h"
#include <cstring>
#include <ctime>

namespace Trade {

/*
# The RiskAction

## The Pet
- master, clear dog and mouse, run the master and cat
- mouse, then pause cat and run the mouse
- dog, run the dog
- cat, run the cat

## The Action is Run/Close/Revere/Open
- Run, means open the dir
- close a portion of the dir
- close all of the dir
- reverse the dir
- open more volume

## The Action is renew
- renew the timer of the pet(s)
- renew the lines and timer of the pet(s)
- if the pet is master, then renew the master as well as the cat

## The Strategy
- for the Conservative Strategy, ra->action = RISK_ACTION::CLOSE_PORTION;
- for the Progressive Strategy, ra->action = RISK_ACTION::DO_NOTHIGN
- for the Crazy Strategy, ra->action = RISK_ACTION::DO_MORE

*/

enum class ENERGY_COMPARE_RESULT : uint8_t
{
  NONE = 0,
  UNKNOW = 1,                    // i do not know
  STILL_KEEP = 2,                // still keep energy and timer
  LOST_ENERGY = 3,               // lost the energy
  LOST_TIMER = 4,                // lost the timer
  LOST_ENERGY_TIMER = 5,         // lost energy and lost timer
  ENERGY_CHANGED = 6,            // but keep timer
  ENERGY_CHANGED_LOST_TIMER = 7, // energy was changed and lost timer
};

struct EnergyChanged
{
  bool changed = false;
  uint8_t time_amount = 0;
  uint8_t force_amount = 0;
  uint8_t g2_amount = 0;
  uint8_t all_amout = 0;

  void reset() { memset((void*)(this), 0, sizeof(EnergyChanged)); }

  void print() const noexcept;
};

enum class BATTLE_RESULT : uint8_t
{
  NONE = 0,
  UNKNOW,
  STRONG,
  ALIKE,
  WEAK,
};

enum class ENERGY_STATE : uint8_t
{
  NONE = 0,
  NOFORCE = 1,
  FORCE = 2,
  ENERGY = 3,
  ZZ = 4,
  ZZZZ = 5,
};

struct EnergyMark
{
  dir_t dir = 0;
  case_t timing_case = 0;
  bool same_spp_dir = false;
  bool same_wave_dir = false;
  bool large_reflection = false;
  bool same_g2_dir = false;
  bool g2_oppo_dir = false;
  bool same_mid_ein_dir = false;
  bool nice_region = false;
  bool spot_without_spp = false;
  bool two_g2_1st_to = false;
  bool two_g2_1st_good = false;
  bool vss_to_same_wave = false;
  bool min_ein_opposite = false;
  bool force_solved_one_spp = false;
  bool time_solved_one_spp = false;
  bool energe_without_spp = false;
  bool sure_vss_spp_dir = false;
  bool mid_zero_other_same = false;
  bool one_spp_solved_dir = false;
  bool diff_mid_ein_same_spp = false;
  bool mid_ein_oppo_but_g2_to = false;
  bool diff_cls_ein_g2_2type = false;
  bool one_spp_and_first_and_g2 = false;
  bool zzzz_g2_and_first = false;
  bool zzzz_and_no_g2 = false;
  uint8_t zz_or_zzzz = 0;
  ENERGY_STATE state;
  case_t force_case = 0;

public:
  void reset() noexcept { memset((void*)(this), 0, sizeof(EnergyMark)); }
  void print(const char* title) noexcept;
};

struct EnergyDir
{
  dir_t dir = 0;
  uint32_t up_case = 0;
  uint32_t dn_case = 0;
  int64_t idx = 0;
  time_t tm = 0;
  price_t hpx = 0;

  void reset() noexcept { memset((void*)(this), 0, sizeof(EnergyDir)); }
  void print(const price_t hp_now, const time_t t_now) const noexcept;
};

#define LONGER_10M(tm) (longer_than((tm), t_now_, MINUTES_10))
#define LONGER_15M(tm) (longer_than((tm), t_now_, MINUTES_15))
#define LONGER_30M(tm) (longer_than((tm), t_now_, MINUTES_30))
#define LONGER_45M(tm) (longer_than((tm), t_now_, MINUTES_45))
#define LONGER_AN_HOUR(tm) (longer_than((tm), t_now_, AN_HOUR))
#define LONGER_ONE_HALF(tm) (longer_than((tm), t_now_, ONE_HALF_HOUR))
#define LONGER_TWO_HOURS(tm) (longer_than((tm), t_now_, TWO_HOURS))
#define LONGER_4_HOURS(tm) (longer_than((tm), t_now_, (TWO_HOURS + TWO_HOURS)))
#define LESS_TWO_HOURS(tm) (less_than((tm), t_now_, TWO_HOURS))
#define LESS_AN_HOUR(tm) (less_than((tm), t_now_, AN_HOUR))
#define LESS_ONE_HALF(tm) (less_than((tm), t_now_, ONE_HALF_HOUR))
#define LESS_45MIN(tm) (less_than((tm), t_now_, MINUTES_45))
#define LESS_30MIN(tm) (less_than((tm), t_now_, MINUTES_30))
#define LESS_15MIN(tm) (less_than((tm), t_now_, MINUTES_15))
#define LESS_10MIN(tm) (less_than((tm), t_now_, MINUTES_10))
#define ABOUT_TIME_DELTA(tm, now, td)                                          \
  (((tm) - (now) < (td)) && ((tm) - (now) > (-(td))))

} // namespace Trades
